package com.syyo.admin.common.security;

import com.syyo.admin.common.anno.AnonymousAccess;
import com.syyo.admin.common.anno.SysLog;

import com.syyo.admin.common.enums.ResultEnum;
import com.syyo.admin.domain.ResultVo;

import com.syyo.admin.common.security.config.SecurityProperties;
import com.syyo.admin.common.security.config.TokenProvider;
import com.syyo.admin.domain.req.UserReq;
import com.syyo.admin.utils.ResultUtils;
import com.syyo.admin.utils.SecurityUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: wangzhong
 * @Date: 2020/4/27 17:13
 * @Description: 认证接口
 */
@RestController
@RequestMapping("/auth")
public class AuthController {

    private final TokenProvider tokenProvider;
    private final SecurityProperties properties;
    private final UserDetailsService userDetailsService;
    private final AuthenticationManagerBuilder authenticationManagerBuilder;

    public AuthController(SecurityProperties properties,
                          AuthenticationManagerBuilder authenticationManagerBuilder,
                          TokenProvider tokenProvider,
                          UserDetailsService userDetailsService) {
        this.properties = properties;
        this.tokenProvider = tokenProvider;
        this.userDetailsService = userDetailsService;
        this.authenticationManagerBuilder = authenticationManagerBuilder;
    }

    @SysLog("登录测试")
    @AnonymousAccess
    @PostMapping("/login")
    public ResultVo login(@RequestBody UserReq authUser){
        String password = authUser.getPassWord();
        String username = authUser.getUserName();
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(username, password);

        // 调用 loadUserByUsername,因为同一异常处理器捕捉不到异常，所以在这里捕捉
        try {
            Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 生成令牌
            String token = tokenProvider.createToken(authentication);

            //获取jwtUser对象
            final JwtUser jwtUser = (JwtUser) authentication.getPrincipal();

            // 返回 token 与 用户信息
            Map<String,Object> authInfo = new HashMap<String,Object>(2){{
                put("token", properties.getTokenStartWith() + token);
                put("user", jwtUser);
            }};
            return ResultUtils.ok(authInfo);
        }catch (BadCredentialsException e){
            ResultVo<Object> resultVo = new ResultVo<>();
            resultVo.setCode(ResultEnum.E_80006.getCode());
            resultVo.setMessage(ResultEnum.E_80006.getMessage());
            return resultVo;
        }catch (InternalAuthenticationServiceException e){
            ResultVo<Object> resultVo = new ResultVo<>();
            resultVo.setCode(ResultEnum.E_80006.getCode());
            resultVo.setMessage(ResultEnum.E_80006.getMessage());
            return resultVo;
        }
    }

    /**
     * 用户退出
     * @param
     * @return
     */
    @AnonymousAccess
    @PostMapping("/logout")
    public ResultVo logout(HttpServletRequest request){
        //删除redis的token
        return ResultUtils.ok(1);
    }

    /**
     * info
     * @param
     * @return
     */
    @GetMapping("/info")
    public ResultVo getUserInfo(){
        return ResultUtils.ok(userDetailsService.loadUserByUsername(SecurityUtils.getUsername()));
    }
}
